/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-04
 * V4.0
 */
package com.jphenix.kernel.objectloader.interfaceclass;

import java.util.List;

import com.jphenix.driver.propertie.instanceb.XmlConfProp;
import com.jphenix.kernel.classloader.ResourceService;
import com.jphenix.kernel.classloader.ResourcesLoader;
import com.jphenix.kernel.objectloader.vo.BeanVO;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.log.ILogShadow;

/**
 * 类加载器接口
 * 
 * 状态
 * 			 0~99		 停止类
 * 			 100~199	 启动中类
 * 			 200~299 	运行中类
 * 			 300~399	暂停类
 * 			 400~499	停止中类
 * 			 500~599	异常
 * 
 * 
 * 获取类实例需要传入类主键，和获取类实例的对象
 * 
 * 类主键实际上就是与获取类实例对象同级文件夹下的配置文件名，配置文件中
 * 包含了真正的类主键，所属的类工厂主键（插件主键）。
 * 
 * 这样做的目的在于可以判断出一个应用依赖的类或者插件
 * 
 * 配置文件中只能有一个类描述信息
 * 
 * 2018-09-05 从IBeanFactoryManager接口中迁移过来getConfProp()方法
 * 2018-09-13 简化了整个架构中日志初始化步骤
 * 2019-01-18 增加了获取全局包资源管理服务方法
 * 2020-08-06 修改了配置文件处理接口，改为直接使用实体类
 * 2022-02-08 将getClassLoader方法从IBeanFactoryManager迁移到这里，也挺常用的
 * 2024-06-05 取消扩展库功能，改用：在WEB-INF/lib中创建子文件夹将jar包归类
 * 2024-08-17 适配了嵌入Spring架构
 * 
 * @author 马宝刚
 * 2009-11-18 下午04:22:08
 */
@ClassInfo({"2024-08-17 23:20","类加载器接口"})
public interface IBeanFactory {

	/**
	 * 日志配置文件路径
	 */
	String TAG_LOG_CONFIG_FILE_PATH = "logConfigFilePath";
	
	/**
	 * 配置文件中的常量段
	 */
	String TAG_PROPERTIES = "properties";
	
	/**
	 * 参数配置文件路径
	 */
	String TAG_PROPERTIES_FILE_PATH = "propertiesFilePath";
	
	/**
	 * 开发时使用的配置文件路径
	 * 如果存在该文件，就不会再读取参数配置文件路径（即：TAG_PROPERTIES_FILE_PATH）
	 * 有了这个功能，可以将配置文件放到webroot文件夹外面，在部署项目时，直接将webroot
	 * 文件夹复制到生产环境，就不用再修改配置文件中连接生产数据库等信息了。
	 */
	String TAG_DEVELOP_PROPERTIES_FILE_PATH = "developPropertiesFilePath";
	
	/**
	 * 引用子配置文件标签名
	 */
	String TAG_IMPORT = "import";
	
	/**
	 * 搜索指定文件夹中的类
	 */
	String TAG_SEARCH = "search";
	
	/**
	 * 路径标签
	 */
	String TAG_PATH = "path";
	
	/**
	 * 子配置文件路径标签名
	 */
	String TAG_IMPORT_FILE_PATH = "filepath";
	
	/**
	 * 类声明标签名
	 */
	String TAG_BEAN = "bean";
	
	/**
	 * 类主键
	 */
	String TAG_BEAN_ID = "id";
	
	/**
	 * 屏蔽类属性
	 */
	String TAG_BEAN_DISABLED = "disabled";
	
	/**
	 * 类路径
	 */
	String TAG_BEAN_CLASS = "class";
	
	/**
	 * 在加载全部类后调用的方法标签
	 */
	String TAG_AFTER_START_METHOD = "after-start-method";
	
	/**
	 * 类失效之前调用的方法名标签
	 */
	String TAG_BEAN_DESTROY_METHOD = "destroy-method";
	
	/**
	 * 初始化方法名
	 */
	String TAG_BEAN_INIT_METHOD = "init-method";
	
	/**
	 * 继承的父类主键
	 */
	String TAG_BEAN_PARENT_ID = "parentid";
	
	
	/**
	 * 调用注册类主键
	 */
	String TAG_BEAN_REGISTER_ID = "bean-register";
	
	/**
	 * 是否驻留内存标签
	 */
	String TAG_BEAN_SINGLETON = "singleton";
	
	/**
	 * 类设置的参数段
	 */
	String TAG_BEAN_PROPERTY = "property";
	
	/**
	 * 是否需要动态部署
	 */
	String TAG_BEAN_DYNAMIC_DEPLOY = "dynamic-deploy";
	
	/**
	 * 参数名
	 */
	String TAG_BEAN_PROPERTY_NAME = "name";
	
	/**
	 * 参数变量名
	 */
	String TAG_BEAN_PROPERTY_VAR = "var";
	
	/**
	 * 参数类型Map中的元素标签名
	 */
	String TAG_BEAN_PROPERTY_MAP_VALUE = "value";
	
	/**
	 * 参数类型Map中的主键属性名
	 */
	String TAG_BEAN_PROPERTY_MAP_KEY = "key";
	
	
	/**
	 * 参数元素中的路径标识属性
	 */
	String TAG_BEAN_PROPERTY_ATTRIBUTE_PATH = "path";
	
	
	/**
	 * 参数类型list中的元素标签名
	 */
	String TAG_BEAN_PROPERTY_LIST_ELEMENT = "value";
	
	/**
	 * 引用类的主键属性名
	 */
	String TAG_BEAN_PROPERTY_REF = "bean";
	
	/**
	 * 是否为抽象父类
	 */
	String TAG_BEAN_ISPARENT = "isparent";
	
	/**
	 * 工厂类根路径
	 */
	String TAG_BEAN_FACTORY_BASE_PATH = "factoryBasePath";
	
	/**
	 * 停止 标识开始
	 */
	int STATE_REST_BEGIN = 0;
	
	/**
	 * 停止  标识结束
	 */
	int STATE_REST_END = 99;
	
	/**
	 * 启动中 标识开始
	 */
	int STATE_START_BEGIN = 100;
	
	/**
	 * 启动中 标识结束
	 */
	int STATE_START_END = 199;
	
	/**
	 * 运行中 标识开始
	 */
	int STATE_RUN_BEGIN = 200;
	
	/**
	 * 运行中 标识结束
	 */
	int STATE_RUN_END = 299;
	
	/**
	 * 暂停 标识开始
	 */
	int STATE_PAUST_BEGIN = 300;
	
	/**
	 * 暂停 标识结束
	 */
	int STATE_PAUST_END = 399;
	
	/**
	 * 停止中 标识开始
	 */
	int STATE_STOP_BEGIN = 400;
	
	/**
	 * 停止中 标识结束
	 */
	int STATE_STOP_END = 499;
	
	/**
	 * 异常 标识开始
	 */
	int STATE_EXCEPTION_BEGIN = 500;
	
	/**
	 * 异常 标识结束
	 */
	int STATE_EXCEPTION_END = 599;
	
	/**
	 * 重启标识开始
	 */
	int STATE_RESET_BEGEN = 600;
	
	/**
	 * 重启标识结束
	 */
	int STATE_RESET_END = 699;
	
	/**
	 * 停止 无
	 */
	int STATE_REST_NONE = 0;
	
	/**
	 * 停止 存在该类
	 */
	int STATE_REST_LIVE = 1;
	
	/**
	 * 自动停止
	 */
	int STATE_REST_AUTO = 2;
	
	/**
	 * 手动停止
	 */
	int STATE_REST_MANUAL = 3;
	
	/**
	 * 异常停止
	 */
	int STATE_REST_EXCEPTION = 4;
	
	/**
	 * 卸载
	 */
	int STATE_REST_UNLOAD = 5;
	
	/**
	 * 启动中 加载配置信息
	 */
	int STATE_START_LOADINFO_E = 100;
	
	/**
	 * 启动中 
	 */
	int STATE_START_E = 101;
	
	/**
	 * 测试启动中
	 */
	int STATE_START_TEST_E = 102;

	
	/**
	 * 启动中 加载配置信息完毕
	 */
	int STATE_START_LOADINFO_OK = 104;
	
	
	/**
	 * 启动中 类构建完毕，需要执行配置的初始化方法
	 */
	int STATE_START_NEED_INIT = 105;
	
	/**
	 * 正常运行中
	 */
	int STATE_RUN_MORMAL = 200;
	
	
	/**
	 * 正常测试运行中
	 */
	int STATE_RUN_TEST = 201;
	
	
	/**
	 * 不是常驻内存的类  待命
	 */
	int STATE_RUN_STANDBY = 202;
	
	/**
	 * 暂停  调用等待回复
	 */
	int STATE_PAUSE_WAIT_E = 300;
	
	/**
	 * 暂停 调用抛出异常
	 */
	int STATE_PAUSE_EXCEPTION_E = 301;
	
	/**
	 * 停止中 自动停止中
	 */
	int STATE_STOP_AUTO_E = 403;
	
	/**
	 * 停止中 手动停止中
	 */
	int STATE_STOP_MANUAL_E = 404;
	
	/**
	 * 停止中 异常停止中
	 */
	int STATE_STOP_EXCEPTION_E = 405;
	
	/**
	 * 初始化信息异常
	 */
	int STATE_EXCEPTION_INFO = 501;
	
	/**
	 * 构建时发生异常
	 */
	int STATE_EXCEPTION_LOAD = 502;
	
	/**
	 * 配置类时发生异常
	 */
	int STATE_EXCEPTION_INIT = 503;
	
	/**
	 * 运行时异常
	 */
	int STATE_EXCEPTION_RUN = 504;
	
	/**
	 * 终止时发生异常
	 */
	int STATE_EXCEPTION_DESTROY = 505;
	
	
	/**
	 * 重启  自动重启
	 */
	int STATE_RESET_AUTO_E = 600;
	
	/**
	 * 重启  手动重启
	 */
	int STATE_RESET_MANUAL_E = 601;
	
	/**
	 * 重启 异常重启
	 */
	int STATE_RESET_EXCEPTION_E = 602;
	
	/**
	 * 获取指定接口的类实例
	 * 马宝刚
	 * 2009-11-18 下午04:29:38
	 * @param objInterface 带获取的类实例符合的接口
	 * @param loader 加载者
	 * @throws Exception 执行发生异常
	 * @return 指定接口的类实例
	 */
	<T> T getObject(Class<T> objInterface,Object loader) throws Exception;
	
	/**
	 * 获取指定类实例
	 * 在项目开发时禁止使用
	 * 因为无法通过程序获取类之间的依赖性
	 * 刘虻
	 * 2010-4-14 下午03:23:31
	 * @param beanID 类主键
	 * @param loader 加载者
	 * @return 类实例
	 * @throws Exception 执行发生异常
	 */
	<T> T getObject(String beanID,Object loader) throws Exception;
	
	/**
	 * 获取指定类状态
	 * 刘虻
	 * 2010-2-2 下午05:35:06
	 * @param objInterface 带获取的类实例符合的接口
	 * @throws Exception 执行发生异常
	 * @return 指定类状态
	 */
	int getObjectState(Class<?> objInterface) throws Exception;
	
	/**
	 * 执行初始化
	 * 马宝刚
	 * 2009-11-18 下午04:45:11
	 * @param debugMode 是否为测试模式 该模式下所有加载的类都为测试模式
	 * @return 通过配置文件加载的类主键序列
	 * @throws Exception 执行发生异常
	 */
	List<String> init(boolean debugMode) throws Exception;
	
	/**
	 * 终止类加载器
	 * 
	 * 终止以后就不能再启动了，因为类加载器会释放所有信息
	 * 
	 * @param state 停止状态标识
	 * @throws Exception 执行发生异常
	 * 马宝刚
	 * 2009-11-18 下午04:45:41
	 */
	void destroy(int state) throws Exception;
	
	/**
	 * 重置类加载器
	 * 
	 * 不重置其子类加载器
	 * 
	 * @param state 重启状态标识
	 * @throws Exception 执行发生异常
	 * 马宝刚
	 * 2009-11-18 下午04:45:57
	 */
	void reset(int state) throws Exception;
	
	/**
	 * 获取当前类加载器状态
	 * 马宝刚
	 * 2009-11-18 下午04:47:02
	 * @return 当前类加载器状态
	 */
	int getState();
	
	/**
	 * 获取类加载器根路径
	 * 马宝刚
	 * 2009-11-18 下午05:22:21
	 * @return 类加载器根路径
	 */
	String getWebInfPath();
	
	/**
	 * 获取可读写的资源文件根路径
	 * @return 可读写的资源文件根路径
	 * 2024年3月12日
	 * @author MBG
	 */
	public String getFileSourcePath();
	
	/**
	 * 设置指定类状态
	 * 刘虻
	 * 2010-2-2 下午05:58:49
	 * @param objInterface 带获取的类实例符合的接口
	 * @param state 控制状态
	 * @throws Exception 执行发生异常
	 * 
	 * 	接口中末尾为_E 的都是控制状态
	 */
	void setObjectState(Class<?> objInterface,int state) throws Exception;
	
	
	/**
	 * 添加指定配置文件中的类
	 * 刘虻
	 * 2010-2-3 下午02:19:45
	 * @param loader 执行添加类
	 * @param configFilePath 配置文件相对路径
	 * @return 通过配置文件加载的类主键序列
	 * @throws Exception 执行发生异常
	 */
	List<String> addBean(String configFilePath) throws Exception;
	
	
	/**
	 * 通过类文件路径，构造指定类，尝试获取类内部的（或其父类的 ) PARENT_BEAN_ID 
	 * 值，通过该值获取其父配置信息，按照父配置信息配置当前类
	 * 刘虻
	 * 2012-12-11 下午3:41:36
	 * @param classFilePath 类文件路径
	 * @return 加载后的类主键
	 */
	String addBeanByClassFilePath(String classFilePath);
	
	
	/**
	 * 通过类文件路径，构造指定类，尝试获取类内部的（或其父类的 ) PARENT_BEAN_ID 
	 * 值，通过该值获取其父配置信息，按照父配置信息配置当前类
	 * 刘虻
	 * 2012-12-11 下午3:41:36
	 * @param classFilePath 类文件路径
	 * @param cl 专用类加载器
	 * @return 加载后的类主键
	 */
	String addBeanByClassFilePath(String classFilePath,ClassLoader cl);
	
	/**
	 * 添加其它类路径(全路径)
	 * 刘虻
	 * 2010-2-10 下午01:38:59
	 * @param classPath 类路径(全路径)
	 */
	void addClassPath(String classPath);
	
	
	/**
	 * 判断指定类是否存在
	 * 刘虻
	 * 2010-2-10 下午01:47:21
	 * @param objInterface 带获取的类实例符合的接口
	 * @return 指定类是否存在
	 */
	boolean beanExists(Class<?> objInterface);
	
	
	/**
	 * 判断指定类是否存在
	 * 刘虻
	 * 2010-4-21 下午01:09:42
	 * @param beanID 类主键
	 * @return 指定类是否存在
	 */
	boolean beanExists(String beanID);
	
	
	/**
	 * 当获取的类发生了异常，将该异常设置到类加载器中
	 * 该类加载器处理异常信息
	 * 
	 * 比如无法再次调用该类，通过接口获取异常信息
	 * 刘虻
	 * 2010-2-12 上午11:02:51
	 * @param objInterface 带获取的类实例符合的接口
	 * @param exceptionInfo 该类实例的异常信息
	 * @throws Exception 执行发生异常
	 */
	void setBeanException(Class<?> objInterface,String exceptionInfo) throws Exception;
	
	/**
	 * 是否为调试模式
	 * 拟废弃。从开发这个模式后，几乎从没用过这个模式。
	 * 刘虻
	 * 2010-3-30 下午06:00:16
	 * @return 调试模式
	 */
	boolean isDebugMode();
	
	
	/**
	 * 获取类信息容器
	 * 刘虻
	 * 2010-3-30 下午06:07:14
	 * @param objInterface 带获取的类实例符合的接口
	 * @param loader 加载者
	 * @throws Exception 执行发生异常
	 * @return 类信息容器
	 */
	BeanVO getBeanVO(Class<?> objInterface,Object loader) throws Exception;

	/**
	 * 获取类信息容器
	 * @param beanID 类主键
	 * @param loader 加载者
	 * @return 类信息容器
	 * @throws Exception 执行发生异常
	 * 2017年3月25日
	 * @author MBG
	 */
	BeanVO getBeanVO(String beanID,Object loader) throws Exception;
	
	
	/**
	 * 在类加载器全部加载完毕后需要调用该方法
	 * 执行设置了after-start-method 属性的方法
	 * 
	 * 注意：该方法只能作用于当前类工厂和其子类工厂
	 * 
	 * @param beanIdList 类主键序列
	 * 刘虻
	 * 2010-4-28 上午11:07:42
	 * @throws Exception 执行发生异常
	 */
	void commitInitBean(List<String> beanIdList) throws Exception;
	
	
	/**
	 * 将类实例设置到类加载器中
	 * 该类实例在类加载器中为常驻类实例,状态为运行中
	 * 刘虻
	 * 2010-5-12 上午11:12:42
	 * @param objInterface 类接口
	 * @param obj 类实例
	 * @throws Exception 执行发生异常
	 */
	void setObject(Class<?> objInterface,Object obj) throws Exception;
	
	/**
	 * 强制转换非当前类加载器的类实例为本地类实例
	 * 刘虻
	 * 2011-1-4 下午05:50:29
	 * @param objInterface 指定接口(本地化接口)
	 * @param loader 类实例（可以使非本模块类实例）
	 * @return 转换后的类实例（可能是影子类）
	 * @throws Exception 执行发生异常
	 */
	Object transformInstance(
			Class<?> objInterface,Object bean) throws Exception;
	
	
	/**
	 * 移出指定类
	 * @param beanID 类主键
	 * 2014年7月31日
	 * @author 马宝刚
	 */
	void removeObject(String beanID);
	
	
	/**
	 * 获取日志影子类
	 * 刘虻
	 * 2010-2-3 下午02:24:29
	 * @return 日志影子类
	 */
	ILogShadow getLogShadow();
    
    
	/**
	 * 将指定类设置到类加载器中
	 * @param cls 受类加载器管控的类
	 * @param needInit 是否需要初始化这个类（如果不需要，是因为最后统一进行初始化用）
	 * @return 返回类主键
	 * 2016年4月8日
	 * @author 马宝刚
	 */
	String setClass(Class<IBean> cls,boolean needInit);
	
	
	/**
	 * 判断类加载器是否启动完毕（运行中）
	 * @return 类加载器是否启动完毕（运行中
	 * 2016年6月13日
	 * @author MBG
	 */
	boolean isStartRun();
	
	/**
	 * 获取其它类路径序列（全文件路径）
	 * @return 其它类路径序列（全文件路径）
	 * 2016年11月7日
	 * @author MBG
	 */
	List<String> getClassPathList();
	
	/**
	 * 返回当前项目名（中文标题）
	 * 在WEB-INF/resfiles/properties.xml 中 <project_name></project_name>
	 * 用来区分测试环境、生产环境、开发环境、集群中的每台服务器
	 * @return 当前项目名
	 * 2018年1月25日
	 * @author MBG
	 */
	String getProjectName();
	
	/**
	 * 返回当前项目代码（英文字符串）
	 * 在WEB-INF/resfiles/properties.xml 中 <project_code></project_code>
	 * 用来区分测试环境、生产环境、开发环境、集群中的每台服务器
	 * 用在在线开发平台的授权码验证
	 * @return 当前项目代码
	 * 2018年1月25日
	 * @author MBG
	 */
	String getProjectCode();
	
	/**
	 * 返回当前项目标识（通常为两个大写字母）
	 * 在WEB-INF/resfiles/properties.xml 中 <project_pin></project_pin>
	 * 用来区分测试环境、生产环境、开发环境、集群中的每台服务器
	 * 用在脚本名后缀，数据主键前缀等
	 * @return
	 * 2018年1月25日
	 * @author MBG
	 */
	String getProjectPin();
	
	/**
	 * 返回是否为开发模式
	 * 
	 * 开发模式：
	 * 
	 * 1.日志模块只输出控制台，并不写入日志文件。
	 * 2.脚本源文件夹中，支持 .disabled 文件，屏蔽指定文件夹（包括子文件夹）中的源文件。
	 *   因为有些脚本只有在生产环境中连接生产库，或调用生产环境目标接口才起作用。在本地环境会报错。
	 *   比如一些定时任务没必要在本地环境跑，即可屏蔽这些脚本。
	 * 3.在自开发程序中，可以调用类加载器中方法判断是否为开发模式，针对不同模式做处理，比如选择性日志输出等。
	 * 
	 * 只有程序员在本机开发时，将本机环境设置为开发模式。切忌在测试环境和生产环境设置为开发模式。
	 * 
	 * @return
	 * 2018年2月7日
	 * @author MBG
	 */
	boolean isDevelopMode();
	
	
	/**
	 * 返回是否存在扩展包文件路径
	 * 
	 * 取消扩展库功能，改用：在WEB-INF/lib中创建子文件夹将jar包归类
	 * 
	 * 有时候，为了要支持某一个功能，要加载大量jar包，比如poi
	 * 如果都放到lib文件夹中，就显得这个文件夹中文件太多太杂，不好管理
	 * 于是就支持了可以将支持某一个功能的包，放入lib的子文件夹中
	 * 
	 * @param extLibPath 相对于 /WEB-INF/lib 的文件路径
	 *                    比如 /WEB-INF/lib/poi  则传入 poi
	 *                    比如 /WEB-INF/lib/ms/ws 则传入 ms/ws
	 * @return           true存在
	 * 2018年3月30日
	 * @author MBG
	 */
	// boolean hasExtLib(String extLibPath);
	
	/**
	 * 返回配置文件类实例
	 * @return 配置文件类实例
	 * 2018年9月5日
	 * @author MBG
	 */
	XmlConfProp getConfProp();
	
	
	/**
	 * 获取包资源管理服务
	 * 
	 * 该服务主要管理SDK加载的第三方jar包。因为SDK中的jar包并不是放在 WEB-INF/lib
	 * 文件夹中，而是在这个文件夹中创建了各个子文件夹，将三方包进行归类管理
	 * 
	 * 或者加载单文件模式的SDK包中 /resources/lib 中的所有jar包
	 * 
	 * @return 包资源管理服务
	 * 2019年1月18日
	 * @author MBG
	 */
	ResourceService getResourceService();
	
	/**
	 * 获取内部的类加载器
	 * 刘虻
	 * 2010-5-7 下午02:03:40
	 * @return 内部的类加载器
	 */
	ClassLoader getClassLoader();
	
	/**
	 * 返回SDK包中/resources 路径下的资源加载器实例
	 * @return SDK包中/resources 路径下的资源加载器实例
	 */
	ResourcesLoader getResourceLoader();
}
